package com.sos.core.game
{
	
	import com.sos.core.Position;
	import com.sos.core.cards.Card;
	import com.sos.core.cards.CardKind;
	import com.sos.core.cards.CardType;
	import com.sos.core.cards.PlayerCard;
	import com.sos.utils.StringUtils;
	import com.sos.logging.Logger;
	
	import flash.events.Event;
	

	public class GamePlayerCard extends PlayerCard
	{
	
		// -------------------------------------------------------------------------------
		// CONSTANTS
		// -------------------------------------------------------------------------------
		
		// JSON properties names
		protected static const		JSON_PROPERTY_MODS:String                   = "mods";
		protected static const		JSON_PROPERTY_MOD_TOT:String				= "tot";
		protected static const		JSON_PROPERTY_MOD_ONGOING:String			= "ongoing";
		
		// Events
		public static const     	EVENT_GAME_PLAYER_CARD_CHANGED:String		= "game_player_card_changed";
		
		
		// -------------------------------------------------------------------------------
		// FIELDS
		// -------------------------------------------------------------------------------
			
		private var _position:Position;
		private var _mods:Vector.<GameMod>;
		private var _gameStats:GameStats;
		private var _modStats:GameStats;
		
		// -------------------------------------------------------------------------------
		// CONSTRUCTOR
		// -------------------------------------------------------------------------------
		
		public function GamePlayerCard(data:Object = null, position:Position = null)
		{
			// Ancestor constructor
			super(CardKind.GAME_INSTANCE);
			// Init
			// LT 2013-03-05 CardKind is now passed in the constructor  _kind = CardKind.GAME_REFERENCE;
			_mods = new Vector.<GameMod>();
			_gameStats = new GameStats();
			_modStats = new GameStats();
			// Clears all
			clear();
			
			//FF 2013-03-18 optional position param added to help with substitutions: GameDeck was missing the Position info
			if (position != null)
				_position = position;
			// If generica data is provided, initializes the card loading the data
			if (data != null) 
			{
				// Check if the provided object is a card
				if (data is PlayerCard)
				{
					set(data as PlayerCard);
				}
				else
				{
					load(data);
				}
			}
		}
		
		// -------------------------------------------------------------------------------
		// PROPERTIES
		// -------------------------------------------------------------------------------
		
		public function get position():Position
		{
			return _position;
		}
		
		public function set position(value:Position):void
		{
			_position = value;
		}		
		
		public function get gameStats():GameStats
		{
			return _gameStats;
		}
		
		public function set gameStats(value:GameStats):void
		{
			_gameStats = value;
		}
		
		public function get modStats():GameStats
		{
			return _modStats;
		}
		
		public function set modStats(value:GameStats):void
		{
			_modStats = value;
		}		
		
		public function get mods():Vector.<GameMod>
		{
			return _mods;
		}		
		
		public function get hasMods():Boolean
		{
			return _mods.length > 0;
		}
		
		public function get canPlayCards():Boolean
		{
			return _gameStats.canPlay && !_gameStats.isExpelled;
		}
		
		[Bindable(event="game_player_card_changed")]
		public function get isValid():Boolean
		{
			return	loaded &&
					!StringUtils.isEmpty(_name);
		}
		
		// -------------------------------------------------------------------------------
		// PRIVATE METHODS
		// -------------------------------------------------------------------------------
		
		// Utilities

		protected function containsMod(mod:GameMod):Boolean
		{
			for (var i:int = 0; i<mods.length; i++)
			{
				if (_mods[i].equals(mod)) return true;
			}
			return false;
		}
		
		internal function updatePosition(pos:Position):void
		{
			_position = pos;
		}
		
		protected function dumpMods(msg:String):void
		{
			var dump:String = StringUtils.substitute("player {0} mods [{1}]: ", _instanceId, _mods.length);
			for (var i:int = 0; i<_mods.length; i++)
			{
				if (i > 0) dump += ", "; 
				dump += _mods[i].toString();
			}
			// Log dup
			//Logger.debug("{0} > {1}", msg, dump);
		}
		
		// DataObject implementation
		
		override protected function validate(data:Object):void
		{
			// Call ancestor
			super.validate(data);
			// JSON properties check
			if (!data.hasOwnProperty(JSON_PROPERTY_MODS)) throwLoadMissingPropError(JSON_PROPERTY_MODS);
			if (!data[JSON_PROPERTY_MODS].hasOwnProperty(JSON_PROPERTY_MOD_TOT)) throwLoadMissingPropError(JSON_PROPERTY_MOD_TOT);
		}
				
		override protected function fill(data:Object):void
		{
			// Locals
			var mods:Vector.<GameMod> = null;
			// Call ancestor
			super.fill(data);
			// Loads each mod
			if (data[JSON_PROPERTY_MODS].hasOwnProperty(JSON_PROPERTY_MOD_ONGOING)) 
			{
				// Raw mods data
				var raw_mods:Array = data[JSON_PROPERTY_MODS][JSON_PROPERTY_MOD_ONGOING];
				// Temporary mod list
				mods = new Vector.<GameMod>();
				for (var i:int = 0; i<raw_mods.length; i++)
				{
					// Creates the new mod and adds it to the temporarty list
					mods.push(new GameMod(raw_mods[i]));
				}
			}
			// Loads the total of mods effects
			_modStats.load(data[JSON_PROPERTY_MODS][JSON_PROPERTY_MOD_TOT]);
			// LT 2013-03-12: Dump dello stato prima della copia
			dumpMods("BEFORE fill()");
			// Calculate the current game stats
			_gameStats.set(_stats, _modStats);
			// Clears the mod list and updates it with the new one
			_mods.splice(0, _mods.length);
			// If mods are present, adds the list to the player list
			if (mods != null)
			{
				for (var j:int = 0; j<mods.length; j++)
				{
					_mods.push(mods[j]);
				}
			}
			// LT 2013-03-12: Dump dello stato prima della copia
			dumpMods("AFTER fill()");
		}
		
		// Events dispatcher
		
		protected function dispatchGamePlayerCardChanged():void
		{
			dispatchEvent(new Event(EVENT_GAME_PLAYER_CARD_CHANGED));
		}
		
		// -------------------------------------------------------------------------------
		// PUBLIC METHODS
		// -------------------------------------------------------------------------------
		
		
		public function getModById(id:uint):GameMod
		{
			// Sets the mods into the player status 
			for (var i:int = 0; i<_mods.length; i++)
			{
				if (_mods[i].id == id) return _mods[i];
			}
			return null;
		}
				
		override public function equals(card:Card):Boolean
		{
			var player:GamePlayerCard = card as GamePlayerCard; 
			return 	super.equals(card) && 
					_position == player.position;
		}
		
		public function set(player:PlayerCard):void
		{
			// Force card type
			_type = player.type;
			// Copy the player
			super.copy(player);
		}
		
		override public function copy(card:Card):void
		{
			// Check card type
			if (card.type != CardType.PLAYER && card.type != CardType.GOALKEEPER) throw new Error("Card should be a PLAYER or GOALKEEPER card");
			// Force card type
			_type = card.type;			
			// Ancestor copy
			super.copy(card);
			// Cast the card
			var gamePlayer:GamePlayerCard = card as GamePlayerCard;
			// Copy data
			_position = gamePlayer.position;
			// LT 2013-03-12: Dump dello stato prima della copia
			dumpMods("BEFORE copy()");
			// Copy objects
			_mods.splice(0, _mods.length); 
			for (var i:int = 0; i < gamePlayer.mods.length; i++)
			{
				// LT 2013-02-26 fix mod cloning errors
				_mods.push(gamePlayer.mods[i].clone());
			}
			_gameStats = gamePlayer.gameStats.clone() as GameStats;
			_modStats = gamePlayer.modStats.clone() as GameStats;
			// LT 2013-03-12: Dump dello stato dopo della copia
			dumpMods("AFTER copy()");
		}
		
		override public function clear():void
		{
			// Call ancestor clear 
			super.clear();
			// Clear objects
			_mods.splice(0, _mods.length);
			_modStats.clear();
			_gameStats.clear();
		}

	}
	
}